#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN = 1005;
vector<int> demo;
double closest[MAXN], lowcost[MAXN];
int m, n;             // m为节点的个数，n为边的数量
double G[MAXN][MAXN]; // 邻接矩阵
double prim()
{
    for (int i = 0; i < m; i++)
    {
        lowcost[i] = INF;
    }
    for (int i = 0; i < m; i++)
    {
        closest[i] = 0;
    }
    closest[0] = -1;             // 加入第一个点，-1表示该点在集合U中，否则在集合V中
    int num = 0,  e = 0; // e为最新加入集合的点
    double ans=0;
    while (num < m - 1)          // 加入m-1条边
    {
        int miedge = -1;
        double micost = INF;
        for (int i = 0; i < m; i++)
            if (closest[i] != -1)
            {
                double temp = G[e][i];
                if (temp < lowcost[i])
                {
                    lowcost[i] = temp;
                    closest[i] = e;
                }
                if (lowcost[i] < micost)
                    micost = lowcost[miedge = i];
            }
        ans += micost;
        demo.push_back(micost);
        closest[e = miedge] = -1;
        num++;
    }
    return ans;
}

struct node
{
    double x, y, h;
} dis[MAXN];

double getDistance(node a, node b)
{
    return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2)) + pow(a.h - b.h, 2);
}

int main()
{

    scanf("%d", &m);

    for (int i = 0; i < m; i++)
        scanf("%lf%lf%lf", &dis[i].x, &dis[i].y, &dis[i].h);
    for (int i = 0; i < m - 1; i++)
        for (int j = i + 1; j < m; j++)
        {
            G[i][j] = getDistance(dis[i], dis[j]);
            G[j][i] = G[i][j];
        }

    printf("%.2lf", prim());
    // for (int i = 0; i < m - 1; i++)
    //     cout << demo[i] << " ";
    return 0;
}